package wiEngine;

import java.util.ArrayList;
import wiBase.WiObject;
import wiBase.WiScheduler;
import wiBase.baseInterface.OnDrawerListener;
import wiBase.baseInterface.OnEventSchedulerListener;
import wiBase.baseObject.Event;
import wiBase.baseObject.Node;
import wiBase.baseObject.Packet;

/**
 * class implement OnEventSchedulerListener. When an Event in time is called by Schedule.
 * @see void write(WiObject) method
 */
public class EventTraceListener implements OnEventSchedulerListener {
    
    private WiScheduler mEngine;
    /**
     * for drawer of graphics.
     */
    ArrayList<OnDrawerListener> mLstDrawListener = null;

    public EventTraceListener(WiScheduler engine) {
	this(engine, null);
    }

    public EventTraceListener(WiScheduler engine, ArrayList<OnDrawerListener> lstDrawListener) {
	this.mEngine = engine;
	this.mLstDrawListener = lstDrawListener;
    }
    /**
     * callback for schedule process event.
     * if type of the event is 'ghost': only update time and do nothing.
     * @param data: event
     */
    @Override
    public void write(WiObject data) {
	Event event = (Event) data;
	String type = event.type;

	long time9E = event.getTime();
	if (time9E > mEngine.getCurrentTime9E()) {
	    mEngine.setCurrentTime9E(time9E);
	    for (WiEngine.OnEngineControlListener listener : ((WiEngine) mEngine)._engineControlListener) {
		synchronized (this) {
		    listener.onUpdateCurrentTime(mEngine.getStartTime9E(), mEngine.getFinishTime9E(), mEngine.getCurrentTime9E());
		}

	    }
	}
	if (type.equals("ghost")) {

	    return;
	}
	event.run(type, event);

	switch (type) {
	    case "send":
	    case "forward":
	    case "receive":
		String srcId = event.sourceId;
		String dstId = event.destId;
		int find2 = 0;
		for (WiObject object : mEngine.getListNodes()) {
		    Node _node_ = (Node) object;
		    if (srcId.equals(_node_.id + "") || dstId.equals(_node_.id + "")) {
			_node_.run(type, event);
			find2++;
			if (find2 == 2) {
			    break;
			}
		    }
		}
		String pckId = event.packetId + "";
		for (WiObject object : mEngine.getListPackets()) {
		    Packet _packet_ = (Packet) object;
		    if (pckId.equals(_packet_.id)) {
			_packet_.run(type, event);
			break;
		    }
		}
		break;
	    case "drop":
		String nodeId = event.nodeId;
		for (WiObject object : mEngine.getListNodes()) {
		    Node _node_ = (Node) object;
		    if (nodeId.equals(_node_.id + "") || nodeId.equals(_node_.id + "")) {
			_node_.run(type, event);
			break;
		    }
		}
		pckId = event.packetId + "";
		for (WiObject object : mEngine.getListPackets()) {
		    Packet _packet_ = (Packet) object;
		    if (pckId.equals(_packet_.id)) {
			_packet_.run(type, event);
			break;
		    }
		}
		break;
	    case "move":
		nodeId = event.nodeId;
		for (WiObject object : mEngine.getListNodes()) {
		    Node _node_ = (Node) object;
		    if (nodeId.equals(_node_.id + "") || nodeId.equals(_node_.id + "")) {
			_node_.run(type, event);
			break;
		    }
		}
		break;
	    case "sleep":
		nodeId = event.nodeId;
		for (WiObject object : mEngine.getListNodes()) {
		    Node _node_ = (Node) object;
		    if (nodeId.equals(_node_.id + "") || nodeId.equals(_node_.id + "")) {
			_node_.run(type, event);
			break;
		    }
		}
		break;
	    case "wake":
		nodeId = event.nodeId;
		for (WiObject object : mEngine.getListNodes()) {
		    Node _node_ = (Node) object;
		    if (nodeId.equals(_node_.id + "") || nodeId.equals(_node_.id + "")) {
			_node_.run(type, event);
			break;
		    }
		}
		break;

	    default:
		break;
	}

	// callback for WiView
	if (this.mLstDrawListener != null) {
	    for (OnDrawerListener listener : this.mLstDrawListener) {
		listener.updateState(event);
	    }
	}
    }
}
